package br.com.eduquiz.session;

import java.util.Calendar;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;

import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Out;
import org.jboss.seam.faces.FacesMessages;
import org.jboss.seam.international.StatusMessage.Severity;
import org.jboss.seam.log.Log;
import org.jboss.seam.security.Credentials;
import org.jboss.seam.security.Identity;

import br.com.eduquiz.entity.AdministradorGeral;
import br.com.eduquiz.entity.AdministradorGrupo;
import br.com.eduquiz.entity.Auditoria;
import br.com.eduquiz.entity.Grupo;
import br.com.eduquiz.entity.Pessoa;
import br.com.eduquiz.entity.SubGrupo;
import br.com.eduquiz.entity.Usuario;
import br.com.eduquiz.entity.Auditoria.Tipo;
import br.com.eduquiz.entity.Pessoa.Status;
import br.com.eduquiz.util.Tools;

@Name("authenticator")
public class Authenticator {
	
    @Logger 
    private Log log;

    @In 
    private Identity identity;
    
    @In
    private Credentials credentials;
    
    @In
    private EntityManager entityManager;
    
    @In
    private FacesMessages facesMessages;
    
    @In(create=true, required=false)
    private Perfil perfil;

    @SuppressWarnings("unused")
    @In(required=false, create=true)
    @Out(required=false)
    private Usuario usuario;

    @SuppressWarnings("unused")
    @In(required=false, create=true)
    @Out(required=false)
    private SubGrupo subgrupo;

    @SuppressWarnings("unused")
    @In(required=false, create=true)
    @Out(required=false)
    private Grupo grupo;

    @SuppressWarnings("unused")
	@In(required=false, create=true)
    @Out(required=false)
    private AdministradorGrupo administradorGrupo;

    @SuppressWarnings("unused")
    @In(required=false, create=true)
    @Out(required=false)
    private AdministradorGeral administradorGeral;
    
    public boolean authenticate() {
    	Auditoria auditoria = new Auditoria();
		Boolean retorno = false;
    	
    	try {
    		String senha = Tools.encriptar(credentials.getPassword(), Tools.DEFAULT_ALGORITHM_ENCRIPT);

	        Pessoa pessoa = (Pessoa) entityManager.createQuery("FROM Pessoa p WHERE p.email = :email AND p.senha = :senha AND p.status = :status")
		        .setParameter("email", credentials.getUsername())
		        .setParameter("senha", senha)
		        .setParameter("status", Status.Ativo)
		        .getSingleResult();
	        
	        
	        auditoria.setData(Calendar.getInstance());
	        auditoria.setTipo(Tipo.LOGIN);
	        auditoria.setClientIP(Tools.getClientIP());
	        auditoria.setPessoa(pessoa);
	        auditoria.setDescricao("sucesso");
	        
	        /* Exibe mensagem de boas vindas */
	        facesMessages.addFromResourceBundle(Severity.INFO, "login_Welcome", pessoa.getNome());
	        log.info("Usuário '{0}' autenticado, IP: {1}", credentials.getUsername(), auditoria.getClientIP());
	        
	        if (pessoa instanceof Usuario) {
	        	identity.addRole("Usuario");
	        	perfil.setLinkPerfil(Perfil.LINK_USUARIO);
	        	usuario = (Usuario) pessoa;
	        } else if (pessoa instanceof SubGrupo) {
	        	identity.addRole("Subgrupo");
	        	identity.addRole("Usuario");
	        	perfil.setLinkPerfil(Perfil.LINK_SUBGRUPO);
	        	subgrupo = (SubGrupo) pessoa;
	        } else if (pessoa instanceof Grupo) {
	        	identity.addRole("Grupo");
	        	identity.addRole("Subgrupo");
	        	identity.addRole("Usuario");
	        	perfil.setLinkPerfil(Perfil.LINK_GRUPO);
	        	grupo = (Grupo) pessoa;
	        } else if (pessoa instanceof AdministradorGrupo) {
	        	identity.addRole("AdministradorGrupo");
	        	identity.addRole("Grupo");
	        	identity.addRole("Subgrupo");
	        	identity.addRole("Usuario");
	        	perfil.setLinkPerfil(Perfil.LINK_ADMINISTRADOR_GRUPO);
	        	administradorGrupo = (AdministradorGrupo) pessoa;
	        } else if (pessoa instanceof AdministradorGeral) {
	        	identity.addRole("AdministradorGeral");
	        	identity.addRole("AdministradorGrupo");
	        	identity.addRole("Grupo");
	        	identity.addRole("Subgrupo");
	        	identity.addRole("Usuario");
	        	perfil.setLinkPerfil(Perfil.LINK_ADMINISTRADOR_GERAL);
	        	administradorGeral = (AdministradorGeral) pessoa;
	        } 
	        
        	/* Adiciona as roles do usuário */
//        	List<Role> role = pessoa.getRole();
//        	for (Role r : role) {
//				identity.addRole(r.getNome());
//			}
        	
        	retorno = true;
	     	        
    	} catch (NoResultException e) {
    		log.info("Usuario '{0}' não encontrado", credentials.getUsername());
	        auditoria.setDescricao("usuário não encontrado");
    		retorno = false;
    	} catch (NonUniqueResultException e) {
    		log.error("Usuário '{0}' duplicado no sistema", credentials.getUsername());
	        auditoria.setDescricao("usuário duplicado no sistema");
            retorno = true;
    	} finally {
    		entityManager.persist(auditoria);
    	}
    	
    	return retorno;
    }
    
    public String logout() {
    	identity.logout();
    	return "/login.xhtml";
    }

}
